package com.fingard.dsp.bank.directbank.icbc02;

import com.fingard.constant.Format;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqQrySglBatPayDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlReadMode;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class ICBC02SinglePay extends ICBC02Base implements ISinglePay {
    //单笔支付，不需采用流处理方式
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        //返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
        if ("190808A".equals(p_req1908.reqHeader.commandCode)) {//代理汇兑
            tmpRetDetail = d_190808A(p_req1908);
        } else if ("190810".equals(p_req1908.reqHeader.commandCode)) {//境内外币支付
            tmpRetDetail = d_190810(p_req1908);
        } else if ("190811".equals(p_req1908.reqHeader.commandCode)) {//跨境外币支付
            tmpRetDetail = d_190811(p_req1908);
        } else if ("190801".equals(p_req1908.reqHeader.commandCode)) {//归集下拨
            tmpRetDetail = d_190801(p_req1908);
        } else {
            tmpRetDetail = d_190802(p_req1908);
        }
        if ("-1".equals(tmpRetDetail.respCode) && StringHelper.isNullOrEmpty(tmpRetDetail.reqSeqID)) {
            tmpRetDetail.reqSeqID = p_req1908.singleDetail.askNumber;
        }
        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }

    public RetAtsSglDetail d_190808A(ReqSingle p_req1908) throws Exception {
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        bnkPackageID = p_req1908.singleDetail.askNumber;
        bnkfSeqno = p_req1908.singleDetail.askNumber;
        bnkTransCode = "AGTEXCH";
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        //写入ICBC02通用的头部节点
        Date tmpDateNow = new Date();
        writeCommonHeader(xmlWriter);
        xmlWriter.writeElementString("PayType", "1".equals(p_req1908.singleDetail.paySpd) ? "1" : "2");
        xmlWriter.writeElementString("TotalNum", "1");
        String tmpPayAmt = StringHelper.amountMultiply100(p_req1908.singleDetail.payAmount);
        xmlWriter.writeElementString("TotalAmt", tmpPayAmt);
        xmlWriter.writeElementString("SignTime", Format.DateTime17Format.format(tmpDateNow));
        xmlWriter.writeElementString("ReqReserved1", p_req1908.singleDetail.abstractATS);
        xmlWriter.writeElementClosed("ReqReserved2");
        //需要进行对账码拼接以及节点解析，采用XElement进行处理
        //单笔、批量共用节点赋值方法
        XElement tmpXElement = new XElement("rd", "");
        tmpXElement.addChild(new XElement("iSeqno", String.valueOf(1)));
        tmpXElement.addChild(new XElement("PayAgentAccNo", p_req1908.singleDetail.payAct));
        tmpXElement.addChild(new XElement("PayAgentName", p_req1908.singleDetail.payName));
        tmpXElement.addChild(new XElement("PayAccNo", p_req1908.singleDetail.innerAct));
        tmpXElement.addChild(new XElement("PayAccNameCN", p_req1908.singleDetail.innerName));
        tmpXElement.addChild(new XElement("PayAgentBranchInfo", p_req1908.singleDetail.payBankLocation));
        tmpXElement.addChild(new XElement("isICBCAcc", p_req1908.singleDetail.sameBnk));
        tmpXElement.addChild(new XElement("RecAreaName", p_req1908.singleDetail.recAreaName));
        tmpXElement.addChild(new XElement("RecNetName", "1".equals(p_req1908.singleDetail.sameBnk) ? "" : p_req1908.singleDetail.cnapsName));
        tmpXElement.addChild(new XElement("RecAccNameCN", p_req1908.singleDetail.recName));
        tmpXElement.addChild(new XElement("RecAccNo", p_req1908.singleDetail.recAct));
        tmpXElement.addChild(new XElement("RecAgentBranchInfo", p_req1908.singleDetail.cnapsName));
        tmpXElement.addChild(new XElement("CurrType", convertCurToBank(p_req1908.singleDetail.payCur)));
        tmpXElement.addChild(new XElement("PayAmt", StringHelper.amountMultiply100(p_req1908.singleDetail.payAmount)));
        tmpXElement.addChild(new XElement("PayUse", p_req1908.singleDetail.purpose));
        tmpXElement.addChild(new XElement("ReqReserved3", ""));
        tmpXElement.addChild(new XElement("ReqReserved4", ""));
        nodeAnalysis(p_req1908.singleDetail.srcXElement, tmpXElement, getCharset());
        xmlWriter.writeXElement(tmpXElement);

        xmlWriter.writeEndDocument();//写入报文完成
        String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), true);//发送银行

        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            //解析银行返回
            XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                String tmpRetCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                String tmpRetMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = tmpRetMsg;
                    retDetail.reqSeqID = tmpBkReader.getFirstText("/CMS/eb/pub/fSeqno");
                    retDetail.transState = tmpRetCode;
                    retDetail.payInfoCode = tmpRetCode;
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = "/CMS/eb/pub/RetCode节点为空";
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else if (ConnState.FAIL.equals(tmpStrRet[0])) {
            retDetail.respCode = "0";
            retDetail.respInfo = tmpStrRet[1];
            retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
            retDetail.transState = PaymentState.FAIL_Payment;
            retDetail.payInfoCode = tmpStrRet[0];
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }
        return retDetail;
    }

    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        RetAtsSingleBat retAts = new RetAtsSingleBat(p_req1908BAT);

        XmlTextWriter xmlWriter = new XmlTextWriter();
        xmlWriter.autoFormat = false;

        bnkPackageID = p_req1908BAT.reqBatchNO;
        bnkfSeqno = p_req1908BAT.reqBatchNO;
        bnkTransCode = "PAYENT";

        try {
            // CMS/eb/pub/...
            writeBatCommonHeader(xmlWriter);

            // CMS/eb/in/...
            xmlWriter.writeElementString("OnlBatF", "1");
            xmlWriter.writeElementString("SettleMode", "0");
            xmlWriter.writeElementString("TotalNum", p_req1908BAT.totalNum);
            xmlWriter.writeElementString("TotalAmt", StringHelper.amountMultiply100(p_req1908BAT.totalAmt));
            xmlWriter.writeElementString("SignTime", Format.DateTime17Format.format(new Date()));
            xmlWriter.writeElementClosed("ReqReserved1");
            xmlWriter.writeElementClosed("ReqReserved2");

            // CMS/eb/in/rd/...
            int i = 1;
            while (p_req1908BAT.readRecord()) {
                XElement tmpXElement = convertPayRecDetailToBankXElement(p_req1908BAT.readedDetail, i, "","");

                xmlWriter.writeXElement(tmpXElement);

                i++;
            }

            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), true);
            if (tmpStrRet[0].length() == 0) {
                if (tmpStrRet[1].startsWith("errorCode")) {
                    retAts.batRespCode = "-1";
                    retAts.batRespCode = tmpStrRet[1];
                    retAts.batTransState = tmpStrRet[1];
                    retAts.writeAfterDetail();
                    return retAts;
                } else {

                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        String returnCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                        String returnMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                        if (StringHelper.isNullOrEmpty(returnMsg)) {
                            returnMsg = tmpBkReader.getFirstText("/CMS/eb/pub/SerialNo");
                        }
                        retAts.batRespCode = "0";
                        retAts.batRespInfo = returnMsg;
                        retAts.batTransState = returnCode;
                        retAts.batPayInfoCode = returnCode;
                        String fSeqno = tmpBkReader.getFirstText("/CMS/eb/pub/fSeqno");
                        if (fSeqno == null || !fSeqno.equals(p_req1908BAT.reqBatchNO)) {
                            retAts.batRespCode = "-1";
                            retAts.batRespInfo = "响应支付批次号" + fSeqno + "与请求" + p_req1908BAT.reqBatchNO + "不相等";
                        } else {
                            while (tmpBkReader.read("/CMS/eb/out/rd")) {
                                RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
                                XElement tmpRetNode = tmpBkReader.readedXElement;

                                tmpRetDetail.respCode = "0";
                                String iRetCode = tmpRetNode.getSingleTextNotNull("iRetCode");
                                String iRetMsg = tmpRetNode.getSingleTextNotNull("iRetMsg");
                                tmpRetDetail.respInfo = iRetMsg;
                                tmpRetDetail.payInfoCode = iRetCode;
                                String pkInfoCode = this.pickupPayInfoCode(iRetMsg, iRetCode);
                                if(StringHelper.hasAnyChar(pkInfoCode)){
                                	tmpRetDetail.payInfoCode = pkInfoCode;
                                }
                                tmpRetDetail.reqSeqID = tmpRetNode.getSingleText("ERPSqn");
                                tmpRetDetail.transState = StringHelper.joinNotEmpty("+", returnCode, tmpRetNode.getSingleText("Result"));
                                

                                retAts.writeRetDetail(tmpRetDetail);
                            }
                        }
                    } else {
                        retAts.batRespCode = "-1";
                        retAts.batRespInfo = tmpSbMsg.toString();
                    }
                }
            } else if (ConnState.FAIL.equals(tmpStrRet[0])) {
                retAts.batRespCode = "0";
                retAts.batRespInfo = tmpStrRet[1];
                retAts.batTransState = PaymentState.FAIL_Payment;
                retAts.batPayInfoCode = tmpStrRet[0];
                retAts.batBizState = tmpStrRet[0];
            } else {
                retAts.batRespCode = "-1";
                retAts.batRespInfo = tmpStrRet[1];
            }
        } catch (Exception ex) {
            ex.printStackTrace();

            retAts.batRespCode = "-1";
            retAts.batRespInfo = "发生异常：" + LogHelper.getStackTraceFirstLine(ex)+"，详情请见文件日志";

            WriteBankLogLn(ex);
        }

        retAts.writeAfterDetail();
        return retAts;
    }
    
    private String pickupPayInfoCode(String p_msg,String p_cmpCode){
    	int tmpIndex1 = p_msg.indexOf('[');
        if (tmpIndex1 >= 0) {
            int tmpIndex2 = p_msg.indexOf(']', tmpIndex1);
            if (tmpIndex2 > tmpIndex1 + 1) {
                tmpIndex1 = tmpIndex1 + 1;
                String tmpMsgCode = p_msg.substring(tmpIndex1, tmpIndex2).trim();
                if (tmpMsgCode.startsWith("9301") || tmpMsgCode.contains(p_cmpCode.trim())) {
                	return tmpMsgCode;
                }
            }
        }
        return "";
    }

    //190802对外支付
    private RetAtsSglDetail d_190802(ReqSingle p_req1908) throws Exception {
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        bnkPackageID = p_req1908.singleDetail.askNumber;
        bnkfSeqno = p_req1908.singleDetail.askNumber;
        bnkTransCode = "PAYENT";
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        //写入ICBC02通用的头部节点
        Date tmpDateNow = new Date();
        writeCommonHeader(xmlWriter);
        xmlWriter.writeElementString("OnlBatF", "1");
        xmlWriter.writeElementString("SettleMode", "0");
        xmlWriter.writeElementString("TotalNum", "1");
        String tmpPayAmt = StringHelper.amountMultiply100(p_req1908.singleDetail.payAmount);
        xmlWriter.writeElementString("TotalAmt", tmpPayAmt);
        xmlWriter.writeElementString("SignTime", Format.DateTime17Format.format(tmpDateNow));
        xmlWriter.writeElementString("ReqReserved1", p_req1908.singleDetail.abstractATS);
        xmlWriter.writeElementClosed("ReqReserved2");
        //需要进行对账码拼接以及节点解析，采用XElement进行处理
        //单笔、批量共用节点赋值方法
        XElement tmpXElement = convertPayRecDetailToBankXElement(p_req1908.singleDetail, 1, "","");
        if("0.0.1.0".equals(getBankConfig().getMapValueByKey("versionMapping",bnkTransCode))){
            tmpXElement.addChild(new XElement("BankType", ""));
            tmpXElement.addChild(new XElement("FileNames", ""));
            tmpXElement.addChild(new XElement("Indexs", ""));
            tmpXElement.addChild(new XElement("PaySubNo", ""));
            tmpXElement.addChild(new XElement("RecSubNo", ""));
            tmpXElement.addChild(new XElement("MCardNo", ""));
            tmpXElement.addChild(new XElement("MCardName", ""));
        }
        xmlWriter.writeXElement(tmpXElement);
        xmlWriter.writeEndDocument();//写入报文完成

        Map<String, String> payDataMap = new HashMap<String, String>();
        boolean enableRefund = getBankConfig().getValueAsBool("enableRefund");
        if (enableRefund) {
            payDataMap.put("ownact", p_req1908.singleDetail.payAct);
            payDataMap.put("iseqno", "1");
            payDataMap.put("asknumber", p_req1908.singleDetail.askNumber);
            payDataMap.put("amount", p_req1908.singleDetail.payAmount);
            payDataMap.put("oppact", p_req1908.singleDetail.recAct);
            payDataMap.put("oppactname", p_req1908.singleDetail.recName);
        }
        if (isMCardAcc(p_req1908.singleDetail.recAct) || isMCardAcc(p_req1908.singleDetail.payAct)){
            bnkVersion = "0.0.1.0";
        }

        String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), true);//发送银行

        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            //解析银行返回
            XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                if (enableRefund) {
                    savePayDataMapping(payDataMap);
                }

                String tmpRetCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                String tmpRetMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = tmpRetMsg;
                    retDetail.reqSeqID = tmpBkReader.getFirstText("/CMS/eb/pub/fSeqno");
                    if (tmpBkReader.read("/CMS/eb/out/rd")) {
                        retDetail.transState = tmpRetCode + "+" + tmpBkReader.readedXElement.getSingleText("Result");
                        if (!StringHelper.isNullOrEmpty(tmpBkReader.readedXElement.getSingleText("iRetCode"))) {
                            retDetail.payInfoCode = tmpBkReader.readedXElement.getSingleText("iRetCode");
                        }
                        if (!StringHelper.isNullOrEmpty(tmpBkReader.readedXElement.getSingleText("iRetMsg"))) {
                            retDetail.respInfo = tmpBkReader.readedXElement.getSingleText("iRetMsg");
                            String iRetMsg = tmpBkReader.readedXElement.getSingleText("iRetMsg");
                            String pkInfoCode = this.pickupPayInfoCode(iRetMsg, retDetail.payInfoCode);
                            if(StringHelper.hasAnyChar(pkInfoCode)){
                            	retDetail.payInfoCode = pkInfoCode;
                            }
                        }
                    } else {
                        retDetail.transState = tmpRetCode + "+";
                        retDetail.payInfoCode = tmpRetCode;
                    }
                    if (!"0".equals(tmpRetCode) && StringHelper.isNullOrEmpty(retDetail.respInfo)) {
                        retDetail.respInfo = tmpRetMsg;
                    }
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = "/CMS/eb/pub/RetCode节点为空";
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else if (ConnState.FAIL.equals(tmpStrRet[0])) {
            retDetail.respCode = "0";
            retDetail.respInfo = tmpStrRet[1];
            retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
            retDetail.transState = PaymentState.FAIL_Payment;
            retDetail.payInfoCode = tmpStrRet[0];
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }
        return retDetail;
    }

    //190810 境内外币支付
    public RetAtsSglDetail d_190810(ReqSingle p_req1908) throws Exception {
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        bnkPackageID = p_req1908.singleDetail.askNumber;
        bnkfSeqno = p_req1908.singleDetail.askNumber;
        bnkTransCode = "NEWEXCH";
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        //写入ICBC02通用的头部节点
        Date tmpDateNow = new Date();
        writeCommonHeader(xmlWriter);
        xmlWriter.writeElementString("OnlBatF", "1");
        xmlWriter.writeElementString("SettleMode", "0");
        xmlWriter.writeElementString("TotalNum", "1");
        String tmpPayAmt = StringHelper.amountMultiply100(p_req1908.singleDetail.payAmount);
        xmlWriter.writeElementString("TotalAmt", tmpPayAmt);
        xmlWriter.writeElementString("SignTime", Format.DateTime17Format.format(tmpDateNow));
        xmlWriter.writeElementString("CurrType", convertCurToBank(p_req1908.singleDetail.payCur));
        ReqPayRecDetail p_atsDetail = p_req1908.singleDetail;
        XElement tmpXElement = new XElement("rd", "");
        tmpXElement.addChild(new XElement("iSeqno", "1"));
        //PayType 1：加急 2：普通
        if ("1".equals(p_atsDetail.paySpd)) {
            tmpXElement.addChild(new XElement("PayType", "1"));
        } else {
            tmpXElement.addChild(new XElement("PayType", "2"));
        }
        if ("1".equals(p_atsDetail.sameBnk)) {//同行
            tmpXElement.addChild(new XElement("isICBCAcc", "1"));
        } else {
            tmpXElement.addChild(new XElement("isICBCAcc", "0"));
        }
        tmpXElement.addChild(new XElement("PayAccNo", p_atsDetail.payAct));
        tmpXElement.addChild(new XElement("RecBranch", p_atsDetail.recBankLocation));
        tmpXElement.addChild(new XElement("RecAreaName", p_atsDetail.recAreaName));
        tmpXElement.addChild(new XElement("RecAccNo", p_atsDetail.recAct));
        tmpXElement.addChild(new XElement("RecAccNameCN", p_atsDetail.recName));
        tmpXElement.addChild(new XElement("PayAmt", StringHelper.amountMultiply100(p_atsDetail.payAmount)));
        tmpXElement.addChild(new XElement("UseCode", p_atsDetail.useType));
        tmpXElement.addChild(new XElement("UseCN", p_atsDetail.useType));
        tmpXElement.addChild(new XElement("EnSummary", ""));
        tmpXElement.addChild(new XElement("PostScript", p_atsDetail.abstractATS));
        tmpXElement.addChild(new XElement("Summary", p_atsDetail.memo));
        tmpXElement.addChild(new XElement("Ref", p_atsDetail.askNumber));
        tmpXElement.addChild(new XElement("Oref", p_atsDetail.askNumber));
        tmpXElement.addChild(new XElement("ERPSqn", p_atsDetail.askNumber));
        tmpXElement.addChild(new XElement("BusCode", ""));
        tmpXElement.addChild(new XElement("ERPcheckno", ""));
        tmpXElement.addChild(new XElement("CrvouhType", ""));
        tmpXElement.addChild(new XElement("CrvouhName", ""));
        tmpXElement.addChild(new XElement("CrvouhNo", ""));
        tmpXElement.addChild(new XElement("SortCode", ""));
        tmpXElement.addChild(new XElement("BankType", ""));
        tmpXElement.addChild(new XElement("FXInfo", ""));
        tmpXElement.addChild(new XElement("RecName", ""));
        tmpXElement.addChild(new XElement("TranInfo", ""));
        tmpXElement.addChild(new XElement("RecAddr1", ""));
        tmpXElement.addChild(new XElement("RecAddr2", ""));
        tmpXElement.addChild(new XElement("RecAddr3", ""));
        tmpXElement.addChild(new XElement("OperDate", ""));
        xmlWriter.writeXElement(tmpXElement);
        xmlWriter.writeEndDocument();//写入报文完成
        String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), true);//发送银行
        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            //解析银行返回
            XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                String tmpRetCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                String tmpRetMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = tmpRetMsg;
                    retDetail.reqSeqID = tmpBkReader.getFirstText("/CMS/eb/pub/fSeqno");
                    if (tmpBkReader.read("/CMS/eb/out/rd")) {
                        //0：提交成功，等待银行处理1：授权成功，等待银行处理2：等待授权3：等待二次授权4：等待银行答复，落地处理5：主机返回待处理6：被银行拒绝7：处理成功8：指令被拒绝授权9：银行正在处理10：预约11：预约取消95：待核查
                        retDetail.transState = tmpRetCode + "+" + tmpBkReader.readedXElement.getSingleText("Result");
                        if (!StringHelper.isNullOrEmpty(tmpBkReader.readedXElement.getSingleText("iRetCode"))) {
                            retDetail.payInfoCode = tmpBkReader.readedXElement.getSingleText("iRetCode");
                        }
                        if (!StringHelper.isNullOrEmpty(tmpBkReader.readedXElement.getSingleText("iRetMsg"))) {
                            retDetail.respInfo = tmpBkReader.readedXElement.getSingleText("iRetMsg");
                        }
                    } else {
                        retDetail.transState = tmpRetCode;
                        retDetail.payInfoCode = tmpRetCode;
                    }
                    if (!"0".equals(tmpRetCode) && StringHelper.isNullOrEmpty(retDetail.respInfo)) {
                        retDetail.respInfo = tmpRetMsg;
                    }
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = "/CMS/eb/pub/RetCode节点为空";
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else if (ConnState.FAIL.equals(tmpStrRet[0])) {
            retDetail.respCode = "0";
            retDetail.respInfo = tmpStrRet[1];
            retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
            retDetail.transState = PaymentState.FAIL_Payment;
            retDetail.payInfoCode = tmpStrRet[0];
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }
        return retDetail;
    }

    //190811	跨境外币支付
    public RetAtsSglDetail d_190811(ReqSingle p_req1908) throws Exception {//跨境外币支付
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        bnkPackageID = p_req1908.singleDetail.askNumber;
        bnkfSeqno = p_req1908.singleDetail.askNumber;
        bnkTransCode = "KJWHKK";
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        //写入ICBC02通用的头部节点
        Date tmpDateNow = new Date();
        String sameBank = "";
        writeCommonHeader(xmlWriter);
        xmlWriter.writeElementString("SignTime", Format.DateTime17Format.format(tmpDateNow));
        xmlWriter.writeElementString("TotalNum", "1");
        String tmpPayAmt = StringHelper.amountMultiply100(p_req1908.singleDetail.payAmount);
        xmlWriter.writeElementString("TotalAmt", tmpPayAmt);
        xmlWriter.writeElementString("FileList", "");
        xmlWriter.writeElementString("IndexList", "");
        ReqPayRecDetail p_atsDetail = p_req1908.singleDetail;
        XElement tmpXElement = new XElement("rd", "");
        tmpXElement.addChild(new XElement("PayAcctName", p_atsDetail.payName));
        tmpXElement.addChild(new XElement("PayAcctNo", p_atsDetail.payAct));
        tmpXElement.addChild(new XElement("PayENAcctName", ""));
        tmpXElement.addChild(new XElement("PayAddr", "PayAddr"));//汇款人地址 need
        tmpXElement.addChild(new XElement("Phone", "Phone"));//联系电话 need
        if ("1".equals(p_atsDetail.sameBnk)) {
            sameBank = "1";
        } else {
            sameBank = "2";
        }
        tmpXElement.addChild(new XElement("SysIOFlag", sameBank));//need
        tmpXElement.addChild(new XElement("RecAcctName", p_atsDetail.recName));//收款人名称 need
        tmpXElement.addChild(new XElement("RecAcctNo", p_atsDetail.recAct));//收款人账号 need
        tmpXElement.addChild(new XElement("RecAddr", p_atsDetail.recAreaName));//收款人地址
        tmpXElement.addChild(new XElement("RecCountry", "RecCountry"));//收款人常驻国家（地区）及代码
        tmpXElement.addChild(new XElement("RecBankName", p_atsDetail.recBankLocation));//收款人开户行名称need
        if ("1".equals(p_atsDetail.sameBnk)) {
            tmpXElement.addChild(new XElement("RecBankCode", "ICBKNL2AXXX"));//收款人开户行地址 收款人开户行工行时,必须以“ICBK”或“UBHK”开头
        } else {
            tmpXElement.addChild(new XElement("RecBankCode", "BankSwfitCode"));
        }
        String tmpRecCityName = "";
        String tmpRecBankName = p_atsDetail.recBankLocation;
        if (!"1".equals(p_atsDetail.sameBnk)) {//跨行
            //RecCityName 收款方所在城市名称 跨行指令此项必输
            tmpRecCityName = p_atsDetail.recAreaName;
            if (StringHelper.isNullOrEmpty(p_atsDetail.cnapsName)) {
                tmpRecBankName = p_atsDetail.cnapsName;
            }
        }
        tmpXElement.addChild(new XElement("RecBankAddr", tmpRecBankName));//收款人开户行地址
        tmpXElement.addChild(new XElement("RecBankCountry", "RecCountry"));//收款人开户行所在国家
        tmpXElement.addChild(new XElement("RecBankCity", tmpRecCityName));//收款人开户行所在城市
        tmpXElement.addChild(new XElement("RecAgtBankName", ""));//收款银行之代理行名称
        tmpXElement.addChild(new XElement("RecAgeBankAddr", ""));//收款银行之代理行地址
        tmpXElement.addChild(new XElement("CurrType", convertCurToBank(p_atsDetail.payCur)));//汇款币种(32A) need
        tmpXElement.addChild(new XElement("PayAmt", p_atsDetail.payAmount));//汇款金额(32A) need
        tmpXElement.addChild(new XElement("TranNos", p_atsDetail.askNumber));//交易编码 need
        tmpXElement.addChild(new XElement("TPostscripts", p_atsDetail.memo));//交易附言 need
        tmpXElement.addChild(new XElement("TCurrTypes", convertCurToBank(p_atsDetail.payCur)));//相应币种 need
        tmpXElement.addChild(new XElement("TAmts", String.valueOf(tmpPayAmt)));//相应金额 need 单位：分 支持客户上送2组交易编码、交易附言、相应币种、相应金额 格式：相应金额1|相应金额2
        tmpXElement.addChild(new XElement("Postscript", p_atsDetail.memo));//汇款附言 FT类账户必输
        //数据字典：经常项目贸易、经常项目非贸易、资本项目、代理进口
        //0：经常项目贸易；
        //1：经常项目非贸易；
        //2：资本项目；
        //3：代理进口；
        tmpXElement.addChild(new XElement("KXProp", "1"));//款项性质 need
        //数据字典：预付货款、货到付款、退款、其他0：预付货款；1：货到付款；2：退款；3：其他；
        // 款项性质非0时 此字段只能输入2或者3
        tmpXElement.addChild(new XElement("PayProp", "3"));//付款性质 need
        //数据字典：是、否
        //0：否
        //1：是
        //款项性质0时必输；
        //修改字段中文名称为：本款项是否为保税货物项下付款；
        //对于FT类账户的汇款，必输；
        tmpXElement.addChild(new XElement("HXFlag", ""));//是否为进口核销项下付款
        tmpXElement.addChild(new XElement("BSFlag", ""));//收款人是否在保税区
        tmpXElement.addChild(new XElement("ZYDate", ""));//最迟装运日期
        tmpXElement.addChild(new XElement("ContractNo", ""));//合同号
        tmpXElement.addChild(new XElement("BillNo", ""));//发票号
        tmpXElement.addChild(new XElement("BUnitCode", ""));//报关单经营单位代码
        tmpXElement.addChild(new XElement("BPageNo", ""));//报关单号
        tmpXElement.addChild(new XElement("BCurrType", ""));//报关单币种
        tmpXElement.addChild(new XElement("BTotalAmt", ""));//报关单总金额
        tmpXElement.addChild(new XElement("HZAmt", ""));//本次核注金额
        if ("1".equals(p_atsDetail.sameBnk)) {
            tmpXElement.addChild(new XElement("FeePayer", "OUR"));//国内外费用承担 数据字典：汇款人OUR 、收款人BEN、 共同SHA 收款人开户行非工行时必输
            //收方工行，默认OUR
        } else {
            tmpXElement.addChild(new XElement("FeePayer", "SHA"));
        }
        tmpXElement.addChild(new XElement("FeeAcctNo", ""));//汇款费用手续费、邮电费付费账号
        tmpXElement.addChild(new XElement("Remark", ""));//
        tmpXElement.addChild(new XElement("RecSortCode", ""));//
        tmpXElement.addChild(new XElement("ExeDate", ""));//执行日期
        tmpXElement.addChild(new XElement("RateMode", ""));//汇率商定方式
        tmpXElement.addChild(new XElement("Rate", ""));//汇率
        tmpXElement.addChild(new XElement("FxNum", ""));//FX交易参考号
        tmpXElement.addChild(new XElement("AbrhCode", ""));//实时清算代码
        tmpXElement.addChild(new XElement("UniCode", ""));//业务编号
        tmpXElement.addChild(new XElement("BusType", ""));//业务种类
        tmpXElement.addChild(new XElement("PaySeqno", ""));//付款账号序号
        tmpXElement.addChild(new XElement("RecSeqno", ""));//收款人账号序号
        tmpXElement.addChild(new XElement("FeeSeqNo", ""));//汇款费用手续费、邮电费付费账号序号
        tmpXElement.addChild(new XElement("SPNo", ""));//外汇审批件/备案表号/业务编号
        tmpXElement.addChild(new XElement("FHProp", ""));//付汇性质
        tmpXElement.addChild(new XElement("PayCur", ""));//付款账号币种
        tmpXElement.addChild(new XElement("FeeCur", ""));//汇款费用手续费、邮电费付费账号币种
        tmpXElement.addChild(new XElement("Iban", "Iban"));//IBAN账号
        tmpXElement.addChild(new XElement("IfSFHFlg", ""));//是否集中付汇
        tmpXElement.addChild(new XElement("MemberAccNoName", ""));//成员单位账号\户名
        tmpXElement.addChild(new XElement("IfLocalFlg", ""));//是否本地汇款
        tmpXElement.addChild(new XElement("LocalItemSet", ""));//本地清算要素信息
        tmpXElement.addChild(new XElement("RecPhone", ""));//收款人电话
        tmpXElement.addChild(new XElement("PayUse", p_atsDetail.purpose));//汇款用途
        tmpXElement.addChild(new XElement("Summary",p_atsDetail.memo));//摘要
        tmpXElement.addChild(new XElement("RateContrno", ""));//合约编号
        xmlWriter.writeXElement(tmpXElement);
        xmlWriter.writeEndDocument();//写入报文完成
        String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), true);//发送银行
        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            //解析银行返回
            XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                String tmpRetCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                String tmpRetMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = tmpRetMsg;
                    retDetail.reqSeqID = tmpBkReader.getFirstText("/CMS/eb/pub/fSeqno");
                    if (tmpBkReader.read("/CMS/eb/out/rd")) {
                        //0：提交成功，等待银行处理1：授权成功，等待银行处理2：等待授权3：等待二次授权4：等待银行答复，落地处理5：主机返回待处理6：被银行拒绝7：处理成功8：指令被拒绝授权9：银行正在处理10：预约11：预约取消95：待核查
                        retDetail.transState = tmpRetCode + "+" + tmpBkReader.readedXElement.getSingleText("Result");
                        if (!StringHelper.isNullOrEmpty(tmpBkReader.readedXElement.getSingleText("iRetCode"))) {
                            retDetail.payInfoCode = tmpBkReader.readedXElement.getSingleText("iRetCode");
                        }
                        if (!StringHelper.isNullOrEmpty(tmpBkReader.readedXElement.getSingleText("iRetMsg"))) {
                            retDetail.respInfo = tmpBkReader.readedXElement.getSingleText("iRetMsg");
                        }
                    } else {
                        retDetail.transState = tmpRetCode;
                        retDetail.payInfoCode = tmpRetCode;
                    }
                    if (!"0".equals(tmpRetCode) && StringHelper.isNullOrEmpty(retDetail.respInfo)) {
                        retDetail.respInfo = tmpRetMsg;
                    }
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = "/CMS/eb/pub/RetCode节点为空";
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else if (ConnState.FAIL.equals(tmpStrRet[0])) {
            retDetail.respCode = "0";
            retDetail.respInfo = tmpStrRet[1];
            retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
            retDetail.transState = PaymentState.FAIL_Payment;
            retDetail.payInfoCode = tmpStrRet[0];
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }
        return retDetail;
    }

    //内部调拨190812（上划下拨）
    public RetAtsSglDetail d_190801(ReqSingle p_req1908) throws Exception {
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        bnkPackageID = p_req1908.singleDetail.askNumber;
        bnkfSeqno = p_req1908.singleDetail.askNumber;
        bnkTransCode = "GCOLDIS";
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        //写入ICBC02通用的头部节点
        Date tmpDateNow = new Date();
        String primaryAct = p_req1908.singleDetail.primaryAct;//0-上划 1-下拨 其他未主账户
        String payHigherLevelAct = p_req1908.singleDetail.payHigherLevelAct;
        //String payTopLevelAct = p_req1908.singleDetail.payTopLevelAct;
        String recHigherLevelAct = p_req1908.singleDetail.recHigherLevelAct;
        //String recTopLevelAct = p_req1908.singleDetail.recTopLevelAct;
        writeCommonHeader(xmlWriter);
        String recBankCode = !"".equals(p_req1908.singleDetail.recBankCode) ? p_req1908.singleDetail.recBankCode : "102";
        xmlWriter.writeElementString("BankType", recBankCode);//行别
        String bkColDisFlag = "5";
        String bkColDisType = "1";
        if ("0".equals(primaryAct) || payHigherLevelAct.equals(p_req1908.singleDetail.recAct) || primaryAct.equals(p_req1908.singleDetail.recAct)) {
            xmlWriter.writeElementString("AccNo", p_req1908.singleDetail.recAct);
            xmlWriter.writeElementString("MemberAccNo", p_req1908.singleDetail.payAct);
            bkColDisFlag = "1";
        } else if ("1".equals(primaryAct) || recHigherLevelAct.equals(p_req1908.singleDetail.payAct) || primaryAct.equals(p_req1908.singleDetail.payAct)) {
            xmlWriter.writeElementString("AccNo", p_req1908.singleDetail.payAct);
            xmlWriter.writeElementString("MemberAccNo", p_req1908.singleDetail.recAct);
            bkColDisFlag = "2";//1为归集 2为下拨()
        } else if ("2".equals(primaryAct) || (!recHigherLevelAct.equals(p_req1908.singleDetail.payAct) && !payHigherLevelAct.equals(p_req1908.singleDetail.recAct)) ||
                (!primaryAct.equals(p_req1908.singleDetail.recAct) && !primaryAct.equals(p_req1908.singleDetail.payAct))) {
            xmlWriter.writeElementString("AccNo", p_req1908.singleDetail.payAct);
            xmlWriter.writeElementString("MemberAccNo", p_req1908.singleDetail.recAct);
            bkColDisFlag = "5";//5横向调拨
        }
        xmlWriter.writeElementString("CurrType", convertCurToBank(p_req1908.singleDetail.payCur));
        String bkColDisAmt = StringHelper.amountMultiply100(p_req1908.singleDetail.payAmount);
        xmlWriter.writeElementString("ColDisAmt", bkColDisAmt, true);
        xmlWriter.writeElementString("ColDisType", bkColDisType, true);
        xmlWriter.writeElementString("ColDisFlag", bkColDisFlag, true);//1为归集 2为下拨()，5横向调拨
        xmlWriter.writeElementString("InterAcctNo", "", true);
        xmlWriter.writeElementString("DayCalFlag", "", true);
        xmlWriter.writeElementString("AgreeNo", this.getBankConfig().getValueAsString("innerPayAgreeNo"), true);
        xmlWriter.writeElementString("MainAcctNo", this.getBankConfig().getValueAsString("innerPayMainAcctNo"), true);
        xmlWriter.writeElementString("RtclsFlag", "", true);
        xmlWriter.writeElementString("SignTime", Format.DateTime17Format.format(tmpDateNow));
        xmlWriter.writeElementClosed("ReqReserved1");
        xmlWriter.writeElementClosed("ReqReserved2");
        xmlWriter.writeEndDocument();//写入报文完成
        String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), true);//发送银行
        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            //解析银行返回
            XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                String tmpRetCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                String tmpRetMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = tmpRetMsg;
                    retDetail.reqSeqID = tmpBkReader.getFirstText("/CMS/eb/pub/fSeqno");
                    if (tmpBkReader.read("/CMS/eb/out")) {
                        //2：待授权5：未知（未知是一种最终状态，无需批复）6：失败7：成功（ 受理成功；已完成归集或下拨）8：授权拒绝9：处理中（可疑）
                        retDetail.transState = tmpRetCode + "+" + tmpBkReader.readedXElement.getSingleText("Result");
                        retDetail.payInfoCode = retDetail.transState;
                    } else {
                        retDetail.transState = tmpRetCode;
                        retDetail.payInfoCode = tmpRetCode;
                    }
                    if (!"0".equals(tmpRetCode) && StringHelper.isNullOrEmpty(retDetail.respInfo)) {
                        retDetail.respInfo = tmpRetMsg;
                    }
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = "/CMS/eb/pub/RetCode节点为空";
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else if (ConnState.FAIL.equals(tmpStrRet[0])) {
            retDetail.respCode = "0";
            retDetail.respInfo = tmpStrRet[1];
            retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
            retDetail.transState = PaymentState.FAIL_Payment;
            retDetail.payInfoCode = tmpStrRet[0];
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }
        return retDetail;
    }

    //境内外支付查询
    public RetAtsSingle innerOrCrossBorderQry(ReqQrySingle p_req1944) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);

        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
        bnkPackageID = p_req1944.reqHeader.transSeqID;
        if ("190810".equals(p_req1944.reqHeader.commandCode)) {//境内
            bnkTransCode = "QLOCEXCH";
        } else if ("190811".equals(p_req1944.reqHeader.commandCode)) {//境外
            bnkTransCode = "QRYKJWHKK";
        }
        bnkfSeqno = bnkPackageID;
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        try {
            writeCommonHeader(xmlWriter);//写入ICBC02通用的头部节点
        } catch (Exception e) {
            e.printStackTrace();
        }
        xmlWriter.writeElementString("QryfSeqno", p_req1944.askNumber);
        xmlWriter.writeElementClosed("QrySerialNo");
        if ("190811".equals(p_req1944.reqHeader.commandCode)) {
            if (p_req1944.payBankCode.equals(p_req1944.recBankCode)) {
                xmlWriter.writeElementString("IsICBC", "1");
            } else {
                xmlWriter.writeElementString("IsICBC", "2");
            }
        }
        xmlWriter.writeEndDocument();
        try {
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                    String tmpRetMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                    if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                        tmpRetAtsDetail.reqSeqID = tmpBkReader.getFirstText("/CMS/eb/out/QryfSeqno");
                        if (tmpBkReader.read("/CMS/eb/out/rd")) {
                            tmpRetAtsDetail.respCode = "0";
                            String iRetMsg = tmpBkReader.readedXElement.getSingleText("iRetMsg");
                            if (!StringHelper.isNullOrEmpty(iRetMsg)) {
                                tmpRetAtsDetail.respInfo = iRetMsg;
                            } else {
                                tmpRetAtsDetail.respInfo = tmpRetMsg;
                            }
                            String iRetCode = tmpBkReader.readedXElement.getSingleText("iRetCode");
                            if (!StringHelper.isNullOrEmpty(iRetCode)) {
                                tmpRetAtsDetail.payInfoCode = iRetCode;
                            } else {
                                tmpRetAtsDetail.payInfoCode = tmpRetCode;
                            }

                            String tmpResult = "";
                            //0：提交成功待银行处理；1：授权成功待银行处理；2：待一次授权；3：待二次授权；4：等待银行答复；（落地）；5：等待银行处理；6：指令拒绝处理；7：处理成功；8：指令授权拒绝9：银行正在处理；（可疑）；
                            if (tmpBkReader.readedXElement.getSingleText("Result") != null) {
                                tmpResult = tmpBkReader.readedXElement.getSingleText("Result");
                            }
                            tmpRetAtsDetail.transState = tmpRetCode + "+" + tmpResult;//返回银行状态码
                        } else {
                            tmpRetAtsDetail.respCode = "0";
                            tmpRetAtsDetail.respInfo = tmpRetMsg;
                            tmpRetAtsDetail.transState = tmpRetCode;
                            tmpRetAtsDetail.payInfoCode = tmpRetCode;
                            if (StringHelper.isNullOrEmpty(tmpRetAtsDetail.reqSeqID)) {
                                tmpRetAtsDetail.reqSeqID = p_req1944.askNumber;
                            }
                        }
                    } else {
                        tmpRetAtsDetail.respCode = "-1";
                        tmpRetAtsDetail.respInfo = "节点/CMS/eb/pub/RetCode为空";
                    }
                } else {
                    tmpRetAtsDetail.respCode = "-1";
                    tmpRetAtsDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }
        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    //上划下拨查询
    public RetAtsSingle d_190801_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);

        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
        bnkPackageID = p_req1944.reqHeader.transSeqID;
        bnkTransCode = "GQCOLDIS";
        bnkfSeqno = bnkPackageID;
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        try {
            writeCommonHeader(xmlWriter);//写入ICBC02通用的头部节点
        } catch (Exception e) {
            e.printStackTrace();
        }
        xmlWriter.writeElementString("QryfSeqno", p_req1944.askNumber);
        xmlWriter.writeElementClosed("QrySerialNo");
        xmlWriter.writeElementClosed("ReqReserved1");
        xmlWriter.writeElementClosed("ReqReserved2");
        xmlWriter.writeEndDocument();
        try {
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                    String tmpRetMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                    if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                        tmpRetAtsDetail.reqSeqID = tmpBkReader.getFirstText("/CMS/eb/out/QryfSeqno");
                        tmpRetAtsDetail.respCode = "0";
                        String iRetMsg = tmpBkReader.readedXElement.getSingleText("iRetMsg");
                        if (!StringHelper.isNullOrEmpty(iRetMsg)) {
                            tmpRetAtsDetail.respInfo = iRetMsg;
                        } else {
                            tmpRetAtsDetail.respInfo = tmpRetMsg;
                        }
                        String iRetCode = tmpBkReader.readedXElement.getSingleText("iRetCode");
                        if (!StringHelper.isNullOrEmpty(iRetCode)) {
                            tmpRetAtsDetail.payInfoCode = iRetCode;
                        } else {
                            tmpRetAtsDetail.payInfoCode = tmpRetCode;
                        }

                        String tmpResult = "";
                        //2：待授权6：失败7：成功（ 受理成功；已完成归集或下拨）8：授权拒绝9：处理中（可疑）
                        if (tmpBkReader.readedXElement.getSingleText("Result") != null) {
                            tmpResult = tmpBkReader.readedXElement.getSingleText("Result");
                        }
                        tmpRetAtsDetail.transState = tmpRetCode + "+" + tmpResult;//返回银行状态码
                    } else {
                        tmpRetAtsDetail.respCode = "-1";
                        tmpRetAtsDetail.respInfo = "节点/CMS/eb/pub/RetCode为空";
                    }
                } else {
                    tmpRetAtsDetail.respCode = "-1";
                    tmpRetAtsDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }
        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    public RetAtsSingle d_190808A_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);

        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
        bnkPackageID = p_req1944.reqHeader.transSeqID;
        bnkTransCode = "QAGTEXCH";
        bnkfSeqno = bnkPackageID;
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        try {
            writeCommonHeader(xmlWriter);//写入ICBC02通用的头部节点
        } catch (Exception e) {
            e.printStackTrace();
        }
        xmlWriter.writeElementString("QryfSeqno", p_req1944.askNumber);
        xmlWriter.writeElementClosed("QrySerialNo");
        xmlWriter.writeElementClosed("ReqReserved1");
        xmlWriter.writeElementClosed("ReqReserved2");
        xmlWriter.writeStartElement("rd");
        xmlWriter.writeElementString("iSeqno","1");
        xmlWriter.writeElementString("QryiSeqno","1");
        xmlWriter.writeElementClosed("QryOrderNo");
        xmlWriter.writeElementClosed("ReqReserved3");
        xmlWriter.writeElementClosed("ReqReserved4");
        xmlWriter.writeEndDocument();
        try {
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                    String tmpRetMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                    if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                        tmpRetAtsDetail.reqSeqID = tmpBkReader.getFirstText("/CMS/eb/out/QryfSeqno");
                        if (tmpBkReader.read("/CMS/eb/out/rd")) {
                            tmpRetAtsDetail.respCode = "0";
                            String iRetMsg = tmpBkReader.readedXElement.getSingleText("iRetMsg");
                            if (!StringHelper.isNullOrEmpty(iRetMsg)) {
                                tmpRetAtsDetail.respInfo = iRetMsg;
                            } else {
                                tmpRetAtsDetail.respInfo = tmpRetMsg;
                            }
                            String iRetCode = tmpBkReader.readedXElement.getSingleText("iRetCode");
                            if (!StringHelper.isNullOrEmpty(iRetCode)) {
                                tmpRetAtsDetail.payInfoCode = iRetCode;
                            } else {
                                tmpRetAtsDetail.payInfoCode = tmpRetCode;
                            }

                            String tmpResult = "";
                            if (tmpBkReader.readedXElement.getSingleText("Result") != null) {
                                tmpResult = tmpBkReader.readedXElement.getSingleText("Result");
                            }
                            tmpRetAtsDetail.transState = tmpRetCode + "+" + tmpResult;//返回银行状态码
                        }
                    } else {
                        tmpRetAtsDetail.respCode = "-1";
                        tmpRetAtsDetail.respInfo = "节点/CMS/eb/pub/RetCode为空";
                    }
                } else {
                    tmpRetAtsDetail.respCode = "-1";
                    tmpRetAtsDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }
        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    //1944 状态查询
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        //返回ATS的对象

        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        if ("190808A".equals(p_req1944.reqHeader.commandCode)) {
            retAts = d_190808A_QrySglPay(p_req1944);
            return retAts;
        } else if ("190810".equals(p_req1944.reqHeader.commandCode) || "190811".equals(p_req1944.reqHeader.commandCode)) {
            retAts = innerOrCrossBorderQry(p_req1944);
            return retAts;
        } else if ("190812".equals(p_req1944.reqHeader.commandCode)) {//上划下拨查询
            retAts = d_190801_QrySglPay(p_req1944);
            return retAts;
        } else {
            bnkTransCode = "QPAYENT";
        }
        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
        bnkPackageID = p_req1944.reqHeader.transSeqID;

        bnkfSeqno = bnkPackageID;
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        writeCommonHeader(xmlWriter);//写入ICBC02通用的头部节点

		/*
      <QryfSeqno></QryfSeqno>
      <QrySerialNo></QrySerialNo>
      <ReqReserved1></ReqReserved1>
      <ReqReserved2></ReqReserved2>
      <rd>
        <iSeqno></iSeqno>
        <QryiSeqno></QryiSeqno>
        <QryOrderNo></QryOrderNo>
        <ReqReserved3></ReqReserved3>
        <ReqReserved4></ReqReserved4>
      </rd>
		 * */
        xmlWriter.writeElementString("QryfSeqno", p_req1944.askNumber);
        xmlWriter.writeElementClosed("QrySerialNo");
        xmlWriter.writeElementClosed("ReqReserved1");
        xmlWriter.writeElementClosed("ReqReserved2");
        xmlWriter.writeStartElement("rd");
        xmlWriter.writeElementString("iSeqno", "1");
        xmlWriter.writeElementString("QryiSeqno", "1");
        xmlWriter.writeElementClosed("QryOrderNo");
        xmlWriter.writeElementClosed("ReqReserved3");
        xmlWriter.writeElementClosed("ReqReserved4");
        xmlWriter.writeEndDocument();

        try {
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();

                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);

                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                    String tmpRetMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                    if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                        tmpRetAtsDetail.reqSeqID = tmpBkReader.getFirstText("/CMS/eb/out/QryfSeqno");
                        if (tmpBkReader.read("/CMS/eb/out/rd")) {
                            tmpRetAtsDetail.respCode = "0";
                            String instrRetMsg = tmpBkReader.readedXElement.getSingleText("instrRetMsg");
                            String iRetMsg = tmpBkReader.readedXElement.getSingleText("iRetMsg");
                            if (!StringHelper.isNullOrEmpty(instrRetMsg)) {
                                tmpRetAtsDetail.respInfo = instrRetMsg;
                            } else if (!StringHelper.isNullOrEmpty(iRetMsg)) {
                                tmpRetAtsDetail.respInfo = iRetMsg;
                            } else {
                                tmpRetAtsDetail.respInfo = tmpRetMsg;
                            }
                            String instrRetCode = tmpBkReader.readedXElement.getSingleText("instrRetCode");
                            String iRetCode = tmpBkReader.readedXElement.getSingleText("iRetCode");
                            if (!StringHelper.isNullOrEmpty(instrRetCode)) {
                                tmpRetAtsDetail.payInfoCode = instrRetCode;
                            } else if (!StringHelper.isNullOrEmpty(iRetCode)) {
                                tmpRetAtsDetail.payInfoCode = iRetCode;
                            } else {
                                tmpRetAtsDetail.payInfoCode = tmpRetCode;
                            }
                            
                            String pkInfoCode = this.pickupPayInfoCode(tmpRetAtsDetail.respInfo, tmpRetAtsDetail.payInfoCode);
                            if(StringHelper.hasAnyChar(pkInfoCode)){
                            	tmpRetAtsDetail.payInfoCode = pkInfoCode;
                            }else if (!StringHelper.isNullOrEmpty(iRetMsg)){
                            	pkInfoCode = this.pickupPayInfoCode(iRetMsg, tmpRetAtsDetail.payInfoCode);
                            	if(StringHelper.hasAnyChar(pkInfoCode)){
                                	tmpRetAtsDetail.payInfoCode = pkInfoCode;
                            	}
                            }

                            String tmpResult = "";
                            if (tmpBkReader.readedXElement.getSingleText("Result") != null) {
                                tmpResult = tmpBkReader.readedXElement.getSingleText("Result");
                            }
                            if ("0".equals(tmpRetCode) && tmpResult.length() == 0) {
                                if (!StringHelper.isNullOrEmpty(instrRetCode)) {
                                    tmpResult = instrRetCode;
                                }
                            }
                            tmpRetAtsDetail.transState = tmpRetCode + "+" + tmpResult;//返回银行状态码
                        } else if (tmpRetCode.contains("B0116")) {
                            
                            if (canBeNotExist(p_req1944, tmpRetAtsDetail)) {
                            	tmpRetAtsDetail.respCode = "0";
                                tmpRetAtsDetail.respInfo = tmpRetMsg;
                                String tmpResult = "";
                                tmpBkReader.resetReadMode(XmlReadMode.SimpleInnerText);
                                if (tmpBkReader.getSimpleText("Result") != null) {
                                    tmpResult = tmpBkReader.getSimpleText("Result");
                                }
                                tmpRetAtsDetail.payInfoCode = tmpRetCode;
                                if (StringHelper.isNullOrEmpty(tmpRetAtsDetail.reqSeqID)) {
                                    tmpRetAtsDetail.reqSeqID = p_req1944.askNumber;
                                }
                                tmpRetAtsDetail.transState = tmpRetCode + "+" + tmpResult;
                            }
                            
                        } else {
                            tmpRetAtsDetail.respCode = "-1";
                            tmpRetAtsDetail.respInfo = tmpRetMsg;
                        }
                    } else {
                        tmpRetAtsDetail.respCode = "-1";
                        tmpRetAtsDetail.respInfo = "节点/CMS/eb/pub/RetCode为空";
                    }
                } else {
                    tmpRetAtsDetail.respCode = "-1";
                    tmpRetAtsDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }

        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        RetAtsSingleBat retAts = new RetAtsSingleBat(p_req1944BAT.reqHeader);
        retAts.reqBatchNO = p_req1944BAT.reqBatchNO;

        XmlTextWriter xmlWriter = new XmlTextWriter();
        xmlWriter.autoFormat = false;

        bnkPackageID = p_req1944BAT.reqHeader.transSeqID;
        bnkfSeqno = bnkPackageID;
        bnkTransCode = "QPAYENT";

        try {
            // CMS/eb/pub/...
            writeBatCommonHeader(xmlWriter);

            // CMS/eb/in/...
            xmlWriter.writeElementString("QryfSeqno", p_req1944BAT.reqBatchNO);
            xmlWriter.writeElementClosed("QrySerialNo");
            xmlWriter.writeElementClosed("ReqReserved1");
            xmlWriter.writeElementClosed("ReqReserved2");

            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), false);
            //测试用
            //tmpStrRet[0]="";
            //tmpStrRet[1]="<CMS><eb><pub><TransCode>QPAYENT</TransCode><CIS>020090003080482</CIS><ID>DTYQHL001.y.0200</ID><BankCode>102</BankCode><TranDate>20180611</TranDate><TranTime>203736000551</TranTime><fSeqno>2037364039</fSeqno><RetCode>B0116</RetCode><RetMsg>没有符合条件的记录</RetMsg></pub><out><QryfSeqno>18061101403542</QryfSeqno><QrySerialNo></QrySerialNo><OnlBatF></OnlBatF><SettleMode></SettleMode><BusType></BusType><RepReserved1></RepReserved1><RepReserved2></RepReserved2></out></eb></CMS>";
            //测试用
            if (tmpStrRet[0].length() == 0) {
                if (tmpStrRet[1].startsWith("errorCode")) {
                    retAts.batRespCode = "-1";
                    retAts.batRespInfo = tmpStrRet[1];
                    retAts.writeAfterDetail();
                    return retAts;
                } else {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {

                        HashMap<String, ReqQrySglBatPayDetail> mapQryDetail = p_req1944BAT.readAllDetail();

                        String returnCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                        String returnMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                        retAts.batRespCode = "-1";
                        retAts.batRespInfo = returnMsg;
                        if (StringHelper.hasAnyChar(returnCode)) {
                            if ("0".equals(returnCode) || "B0116".equals(returnCode) || "00000".equals(returnCode) || "B0097".equals(returnCode) || "B0067".equals(returnCode) || "B0041".equals(returnCode)) {
                                String tmpQryfSeqno = tmpBkReader.getFirstText("/CMS/eb/out/QryfSeqno");
                                if (tmpQryfSeqno != null && tmpQryfSeqno.equals(retAts.reqBatchNO)) {
                                    retAts.batRespCode = "0";
                                    retAts.batTransState = returnCode;
                                    retAts.batPayInfoCode = returnCode;
                                    int rdCount=0;
                                    while (tmpBkReader.read("/CMS/eb/out/rd")) {
                                    	rdCount++;
                                        RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
                                        XElement tmpRetNode = tmpBkReader.readedXElement;

                                        tmpRetDetail.respCode = "0";

                                        if (tmpRetNode.getSingleTextNotNull("instrRetMsg").length() > 0) {
                                            tmpRetDetail.respInfo = tmpRetNode.getSingleText("instrRetMsg");
                                        }
                                        String iRetMsg = tmpRetNode.getSingleText("iRetMsg");
                                        if (StringHelper.isNullOrEmpty(tmpRetDetail.respInfo)) {
                                            tmpRetDetail.respInfo = tmpRetNode.getSingleText("iRetMsg");
                                        }

                                        String result = tmpRetNode.getSingleText("Result");
                                        if ("0".equals(returnCode) && StringHelper.isNullOrEmpty(result)) {
                                            result = tmpRetNode.getSingleText("instrRetCode");
                                        }

                                        String payInfoCode = tmpRetNode.getSingleText("instrRetCode");
                                        if (StringHelper.isNullOrEmpty(payInfoCode)) {
                                            payInfoCode = tmpRetNode.getSingleText("iRetCode");
                                        }
                                        tmpRetDetail.reqSeqID = tmpRetNode.getSingleText("ERPSqn");

                                        tmpRetDetail.transState = returnCode + "+" + result;
                                        tmpRetDetail.payInfoCode = payInfoCode;
                                        
                                        String pkInfoCode = this.pickupPayInfoCode(tmpRetDetail.respInfo, tmpRetDetail.payInfoCode);
                                        if(StringHelper.hasAnyChar(pkInfoCode)){
                                        	tmpRetDetail.payInfoCode = pkInfoCode;
                                        }else if (!StringHelper.isNullOrEmpty(iRetMsg)){
                                        	pkInfoCode = this.pickupPayInfoCode(iRetMsg, tmpRetDetail.payInfoCode);
                                        	if(StringHelper.hasAnyChar(pkInfoCode)){
                                        		tmpRetDetail.payInfoCode = pkInfoCode;
                                        	}
                                        }
                                        
                                        tmpRetDetail.transAmt = StringHelper.amountDivide100(tmpRetNode.getSingleText("PayAmt"));
                                        if (mapQryDetail.containsKey(tmpRetDetail.reqSeqID)) {
                                            if (tmpRetDetail.transState.contains("B0116")) {
                                                ReqQrySingle tmpReq1944 = new ReqQrySingle(mapQryDetail.get(tmpRetDetail.reqSeqID), p_req1944BAT.reqHeader);
                                                if(canBeNotExist(tmpReq1944, tmpRetDetail)){
                                                	tmpRetDetail.respCode = "0";
                                                }else{
                                                	tmpRetDetail.transState = "";
                                                	tmpRetDetail.respCode = "-1";
                                                }
                                            }

                                            retAts.writeRetDetail(tmpRetDetail);
                                        }
                                    }
                                    if (retAts.batTransState.contains("B0116") && rdCount == 0) {//整批失败
                                        retAts.batRespCode = "-1";
                                        RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
                                        String firstKey=mapQryDetail.keySet().iterator().next();
                                        ReqQrySingle tmpReq1944 = new ReqQrySingle(mapQryDetail.get(firstKey), p_req1944BAT.reqHeader);
                                        if(canBeNotExist(tmpReq1944, tmpRetDetail)){
                                        	retAts.batRespCode = "0";
                                        	tmpRetDetail.respCode = "0";
                                        	tmpRetDetail.reqSeqID = firstKey;
                                        	tmpRetDetail.transState = retAts.batTransState;
                                        	tmpRetDetail.payInfoCode = retAts.batPayInfoCode;
                                        	tmpRetDetail.respInfo = retAts.batRespInfo;
                                        	//retAts.writeRetDetail(tmpRetDetail);//临时开启用，需调整，ATS-10834
                                        }else{
                                        	retAts.batRespInfo = tmpRetDetail.respInfo;
                                        }
                                        //p_req1944BAT.resetRead();
                                        //p_req1944BAT.readRecord();
                                        //ReqQrySingle tmpReq1944 = new ReqQrySingle(tmpDetail, p_req1944BAT.reqHeader);
                                    }
                                } else {
                                    retAts.batRespCode = "-1";
                                    retAts.batRespInfo = "请求QryfSeqno值" + retAts.reqBatchNO + "与响应值" + tmpQryfSeqno + "不相等";
                                }
                            } else {
                                retAts.batRespCode = "-1";
                            }
                        }
                    } else {
                        retAts.batRespCode = "-1";
                        retAts.batRespInfo = tmpSbMsg.toString();
                    }
                }
            } else {
                retAts.batRespCode = "-1";
                retAts.batRespInfo = tmpStrRet[1];
            }
        } catch (Exception ex) {
            ex.printStackTrace();

            retAts.batRespCode = "-1";
            retAts.batRespInfo = ex.getMessage();

            WriteBankLogLn(ex);
        }

        retAts.writeAfterDetail();
        return retAts;
    }
}
